package com.utils.worldcup;

import com.google.common.collect.Lists;
import com.utils.bfs.Graph;

import java.text.DecimalFormat;
import java.util.*;

public class WorldCupUtils {

    private static class SingletonHolder {
        private static final WorldCupUtils INSTANCE = new WorldCupUtils();

    }

    private WorldCupUtils() {

    }

    public static WorldCupUtils getInstance() {
        return WorldCupUtils.SingletonHolder.INSTANCE;
    }


    /**
     * 根据分组统计每个队伍获胜概率
     *
     * @param group      A
     * @param groupA     例如: "卡塔尔", "塞内加尔", "荷兰", "厄瓜多尔"
     * @param eventA     赛程事件
     * @param groupANum1 综合指数
     * @return 概率值
     */
    public String getByGroup(String tip, String group, List<String> groupA, Object[] eventA, List<Double> groupANum1) {
        // 所有选项集合
        LinkedList<String[]> list = new LinkedList<>();
        // 每个路线对应事件
        Map<String, String> map = new HashMap<>();
        // 每个队伍胜利次数
        Map<String, Integer> winMap = new HashMap<>();


        StringBuilder result = new StringBuilder();
        List<String> allLine = new ArrayList<>();
        //初始化根节点
        Graph theGraph = new Graph();
        String[] opArr = new String[]{"#"};
        list.add(opArr);
        //初始化事件分支
        for (int i = 0; i < eventA.length; i++) {
            String label = eventA[i].toString();
            cg(label, (i + 1), group, map, list);
        }
        //根节点以及中间节点
        for (int i = 0; i < list.size(); i++) {
            if (i + 1 == list.size()) {
                break;
            }
            String[] a1 = list.get(i);
            String[] a2 = list.get(i + 1);
            addEdge(theGraph, a1, a2);
        }
        String[] last = list.getLast();
        //叶子节点
        for (String aLast : last) {
            theGraph.addVertex(aLast);
        }

        StringBuilder sb = new StringBuilder();
        List<List<String>> allPathList = theGraph.mst();
        int total = 0;
        for (List<String> onePath : allPathList) {
            if (sb.length() > 0) {
                sb.delete(0, sb.length());
            }
            for (String node : onePath) {
                sb.append(node).append(",");
            }
            String options = sb.substring(2, sb.length() - 1);
            allLine.add(options);
            total += 1;
        }
        for (String line : allLine) {
            // 先给成绩初始化
            double[] scoreA = new double[4];
            String[] all = line.split(",");
            for (String cg : all) {
                String end = map.get(cg);
                if (end.endsWith("平")) {
                    //两支队伍各加+1分
                    String[] op = end.replace("平", "").split("VS");
                    scoreA[groupA.indexOf(op[0].trim())] += 1;
                    scoreA[groupA.indexOf(op[1].trim())] += 1;
                } else if (end.endsWith("主胜")) {
                    //给主胜队伍加+3分
                    String[] op = end.replace("主胜", "").split("VS");
                    scoreA[groupA.indexOf(op[0].trim())] += 3;
                } else if (end.endsWith("客胜")) {
                    //给客胜队伍加+3分
                    String[] op = end.replace("客胜", "").split("VS");
                    scoreA[groupA.indexOf(op[1].trim())] += 3;
                }
            }
            // 得到整数型分数后需要综合让球指数和进球指数算出最新分数
            for (int i = 0; i < scoreA.length; i++) {
                double v = scoreA[i];
                v *= groupANum1.get(i);
                scoreA[i] = v;
            }
            List<Integer> topTow = findTopTow(scoreA);
            String f1 = groupA.get(topTow.get(0));
            String f2 = groupA.get(topTow.get(1));
            totalWin(f1, winMap);
            totalWin(f2, winMap);
        }
        int finalTotal = total;
        winMap.forEach((k, v) -> {
            double p = (v * 100.0) / finalTotal;
            DecimalFormat df = new DecimalFormat(".00");
            String winP = df.format(p);
            result.append(k).append(tip).append("概率：").append(winP).append("%").append("\n");
        });
        return result.toString();
    }

    /**
     * 统计某支队伍胜利次数
     */
    private static void totalWin(String f1, Map<String, Integer> winMap) {
        if (winMap.containsKey(f1)) {
            Integer count = winMap.get(f1);
            winMap.put(f1, ++count);
        } else {
            winMap.put(f1, 1);
        }
    }

    /**
     * 计算最高分的前两组队伍
     */
    private static List<Integer> findTopTow(double[] scoreA) {
        double maxNumber = Double.MIN_VALUE;
        double secMax = Double.MAX_VALUE;
        for (double aScoreA : scoreA) {
            if (aScoreA > maxNumber) {
                secMax = maxNumber;
                maxNumber = aScoreA;

            } else {
                if (aScoreA > secMax) {
                    secMax = aScoreA;

                }
            }
        }
        List<Double> allScore = Lists.newArrayList();
        for (double s : scoreA) {
            allScore.add(s);
        }
        int fi = allScore.indexOf(maxNumber);
        int si = allScore.indexOf(secMax);
        if (si == fi) {
            allScore.set(fi, -1.0);
        }
        return Lists.newArrayList(fi, allScore.indexOf(secMax));
    }

    /**
     * 添加子节点
     */
    private static void addEdge(Graph theGraph, String[] a1, String[] a2) {
        for (String root : a1) {
            //添加叶子根
            theGraph.addVertex(root);
            //再给叶子根添加子节点
            for (String anA2 : a2) {
                theGraph.addEdge(root, anA2);
            }

        }
    }

    /**
     * 分支事件
     */
    private static void cg(String label, int count, String group, Map<String, String> map, LinkedList<String[]> list) {
        String g1 = group + "W" + count;
        String g2 = group + "P" + count;
        String g3 = group + "S" + count;
        map.put(g1, label + " 主胜");
        map.put(g2, label + " 平");
        map.put(g3, label + " 客胜");
        String[] opArr;
        List<String> opCount = Lists.newArrayList(g1, g2, g3);
        opArr = new String[opCount.size()];
        opArr = opCount.toArray(opArr);
        list.add(opArr);
    }


}
